#pragma once

#include <memory>
#include <chrono>
#include <future>
#include <functional>

class Message;
class Response;
class Request
{
public:
    using OnReply = std::function<void(std::shared_ptr<Response> &)>;
    Request(int timeout = 0);
    Request(const OnReply &onReply);

    std::shared_ptr<Message> &message();
    void setMessage(const std::shared_ptr<Message> &msg);
    void setMessage(std::shared_ptr<Message> &&msg);

    std::shared_ptr<Response> &result();
    void setResult(const std::shared_ptr<Response> &ret);
    void setResult(std::shared_ptr<Response> &&ret);

    bool finished() const;
    void setFinished(bool finished);

    bool isTimeout() const;
    bool isTimeout(std::chrono::steady_clock::time_point now) const;

    void wait();

    bool isAsync() const { return m_onReply != nullptr; }
    void reply();

private:
    int m_timeout;
    std::chrono::steady_clock::time_point m_startTime;
    std::chrono::steady_clock::time_point m_endTime;
    std::shared_ptr<Message> m_msg;
    std::shared_ptr<Response> m_res;
    std::promise<void> m_pro;

    OnReply m_onReply;

};
